import path from 'node:path'
import fs from 'fs-extra'
import { execa } from 'execa'
import inquirer from 'inquirer'
import chalk from 'chalk'
import { PKG_NAME, PKG_PLUGIN, packages, proRoot } from './config'
const runRoot = (bin: string, args: string[], opts = {}) =>
  execa(bin, args, { stdio: 'ignore', cwd: proRoot, ...opts })

export function updateVersion(version: string) {
  ;[proRoot, ...packages].forEach((p) => {
    updatePkg(p, version)
  })
}

function updatePkg(pkgRoot: string, version: string) {
  const pkgPath = path.resolve(pkgRoot, 'package.json')
  const pkg = fs.readJSONSync(pkgPath)
  pkg.version = version
  updateDeps(pkg, 'devDependencies', version)
  updateDeps(pkg, 'dependencies', version)
  updateDeps(pkg, 'peerDependencies', version)
  fs.writeJSONSync(pkgPath, pkg, { spaces: 2 })
  console.log(chalk.blueBright(`${pkg.name} is update: ${version}`))
}

function updateDeps(pkg: any, depType: string, version: string) {
  const deps = pkg[depType]
  if (!deps) return
  Object.keys(deps).forEach((dep) => {
    if (dep === PKG_NAME || dep === PKG_PLUGIN) {
      deps[dep] = version
    }
  })
}

export async function updateLockfile() {
  console.log(chalk.greenBright('updating pnpm-lock.yaml'))
  await runRoot('pnpm', ['install', '--prefer-offline'])
  console.log(chalk.greenBright(`pnpm-lock.yaml is update`))
}

export async function buildPackage() {
  await runRoot('pnpm', ['build'], { stdio: 'inherit' })
}

export async function pushGithub(version: string) {
  console.log('committing changes...')
  const { stdout } = await runRoot('git', ['diff'], { stdio: 'pipe' })
  let defaultDescription = `release: v${version}`
  if (stdout) {
    await runRoot('git', ['add', '-A'])
    const { custom } = await inquirer.prompt([
      {
        type: 'confirm',
        name: 'custom',
        message: 'Custom description ?',
        default: false
      }
    ])
    if (custom) {
      const { description } = await inquirer.prompt([
        {
          type: 'input',
          name: 'description',
          message: 'input description',
          default: defaultDescription
        }
      ])
      defaultDescription = description
    }
    await runRoot('git', ['commit', '-m', defaultDescription])
  } else {
    console.log('no changes to commit.')
  }
  console.log('pushing to GitHub...')
  await runRoot('git', ['tag', `v${version}`])
  await runRoot('git', ['push'])
}

export async function publish(pkg: string) {
  const pkgPath = path.resolve(pkg, 'package.json')
  const pkgJson = await fs.readJSON(pkgPath)
  const version = pkgJson.version
  const pkgName = pkgJson.name
  if (pkgJson.private) {
    return
  }
  let releaseTag = null
  if (version.includes('alpha')) {
    releaseTag = 'alpha'
  } else if (version.includes('beta')) {
    releaseTag = 'beta'
  } else if (version.includes('rc')) {
    releaseTag = 'rc'
  }
  try {
    console.log(`publishing ${pkgName}`)
    await execa(
      'pnpm',
      [
        'publish',
        ...(releaseTag ? ['--tag', releaseTag] : []),
        '--no-git-checks',
        '--access',
        'public'
      ],
      {
        cwd: pkg,
        stdio: 'inherit'
      }
    )
    console.log(`Successfully publish ${pkgName}`)
  } catch (error) {
    console.log(error)
  }
}
